// Array implementation of a Trail.

package com.fduss.mazegame.core.groupunit;

import com.fduss.mazegame.core.Update;
import com.fduss.mazegame.core.unit.Footprint;
import com.fduss.mazegame.core.unit.Place;
import com.fduss.mazegame.core.unit.feature.Icon;
import com.fduss.mazegame.util.Queue;
import com.fduss.mazegame.util.QueueLinked;

public class TrailArray implements Trail {

    private Footprint[] tracks;
    private int capacity;
    private int size; // current number of elements in the collection
    private int oldest; // -1 if empty
    private int newest; // -1 if empty
    private QueueLinked<Update> updates;

    public TrailArray(int capacity) {
        if (capacity <= 0) {
            throw new IllegalArgumentException("capacity was <= 0");
        }
        this.capacity = capacity;
        this.tracks = new Footprint[capacity];
        this.size = 0;
        this.oldest = -1;
        this.newest = -1;
        updates = new QueueLinked<>();
    }

    public void add(Place p) {
        if (p == null) {
            throw new NullPointerException("p");
        }
        if (size != capacity) {
            newest = (++newest) % capacity;
            tracks[newest] = new Footprint(p);
            if (size == 0) {
                oldest = 0;
            }
            size++;
            // updates
            Update u = new Update(p, Icon.FOOTPRINT);
            updates.enqueue(u);
        } else {
            Footprint old = tracks[oldest];
            Place oldP = old.getPlace();
            oldP.rmEntity(old);
            // remove old footprint
            updates.enqueue(new Update(oldP, oldP.getIcon()));
            tracks[oldest] = new Footprint(p);
            newest = oldest;
            oldest = (++oldest) % capacity;
            // add new footprint
            updates.enqueue(new Update(p, p.getIcon()));
        }
    }

    public Footprint[] getAll() {
        Footprint[] a = new Footprint[size];
        if (size == 0) {
            return a;
        }
        if (newest >= oldest) {
            for (int i = newest, j = 0; i >= oldest; i--, j++) {
                a[j] = tracks[i];
            }
        } else {
            int j = 0;
            for (int i = newest; i >= 0; i--, j++) {
                a[j] = tracks[i];
            }
            for (int i = capacity - 1; i >= oldest; i--, j++) {
                a[j] = tracks[i];
            }
        }
        return a;
    }

    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("TrailArray[");
        sb.append("capacity=" + capacity);
        sb.append(", size=" + size);
        sb.append(", oldest=" + oldest);
        sb.append(", newest=" + newest);
        sb.append("]");
        return sb.toString();
    }

    public void update(Queue<Update> dest) {
        while (!updates.isEmpty()) {
            dest.enqueue(updates.dequeue());
        }
    }
}
